/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.commands;

import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.Operation;

/**
 * Command that moves an element in a {@link List}.
 * 
 * @author Remi SCHNEKENBURGER
 */
public class MoveConstraintInListCommand extends MoveInListCommand {
	
	/**
	 * The constrained element
	 */
	protected NamedElement constrainedElement;
	
	/**
	 * The kind of constraint
	 */
	protected String constraintKind = "";
	
	/**
	 * Available kind of constraint
	 */
	protected final static String TYPE_PRE  = "PRE";
	protected final static String TYPE_BODY = "BODY";
	protected final static String TYPE_POST = "POST";
	
	/**
	 * Default constructor.
	 * 
	 * @param element the element to move in the given list
	 * @param list the list to be changed
	 * @param newIndex the new index of the element in the given list
	 */
	public MoveConstraintInListCommand(List<Constraint> list, Constraint constraint, int newIndex) {
		super(list, constraint, newIndex);
		
		EList<Element> constrainedElements = constraint.getConstrainedElements();
		if ((constrainedElements != null) 
				&& (constrainedElements.size() > 0)) {
			constrainedElement = (NamedElement) constrainedElements.get(0);
			
			if (constrainedElement instanceof Operation) {
				Operation oper = (Operation) constrainedElement;
				if (oper.getPreconditions().contains(constraint)) {
					constraintKind = TYPE_PRE;
				} else if (oper.getPostconditions().contains(constraint)) {
					constraintKind = TYPE_POST;
				} else if (constraint.equals(oper.getBodyCondition())) {
					constraintKind = TYPE_BODY;
				}
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#execute()
	 */
	/**
	 * 
	 */
	@Override
	public void execute() {
		super.execute();
		updateReferences();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#undo()
	 */
	/**
	 * 
	 */
	@Override
	public void undo() {
		super.undo();
		updateReferences();
	}
	
	private void updateReferences() {
		
		if (constrainedElement != null) {
			((Constraint) element).setContext((Namespace) constrainedElement);
		}
		
		if (constrainedElement instanceof Operation) {
			Operation oper = (Operation) constrainedElement;
			if (TYPE_PRE.equals(constraintKind)) {
				oper.getPreconditions().add((Constraint) element);
			} else if (TYPE_POST.equals(constraintKind)) {
				oper.getPostconditions().add((Constraint) element);
			} else if (TYPE_BODY.equals(constraintKind)) {
				oper.setBodyCondition((Constraint) element);
			}
		}
	}
}
